package view;

import database.DataManager;

import javax.swing.JOptionPane;

import model.Classes;
import model.User;
import model.UserInterface;


/**
 * Model View Controller Patterned Controller class.
 * 
 * @author Tristan D. Boucher
 * @version Commit #22 9/14/2013
 */
public class GUIController
{
  /**
   * The DataManager instance that will be used to query the database.
   */
  private final DataManager my_data_manager;

  /**
   * The Frame that will contain the GUI views and panels.
   */
  private final GUIFrame my_frame;

  /**
   * The field holding the GUIPromotionWindow handle.
   */
  private GUIPromotionWindow my_promotion_window;

  /**
   * The currently logged in user.
   */
  private UserInterface my_current_user;

  /**
   * Constructor constructs all GUI's and readies them in memory
   * for quick display and interface changes.
   * 
   * @param the_data_manager The DataManager instance used in this 
   * controller to query and modify the database.
   */
  public GUIController(final DataManager the_data_manager)
  {
    my_data_manager = the_data_manager;
    
    my_current_user = null;
    
    my_data_manager.addUser(new User("Admin", "istrator", "5516742", "Mittens", true));
    
    my_promotion_window = new GUIPromotionWindow(my_data_manager.requestAllUsers(), this);

    my_frame = new GUIFrame(new GUIMenuBar(this), new GUILoginPanel(this));

    my_frame.setVisible(true);
     
    showLoginPanel();
  }

  /**
   * Adds a new user to the database.
   * 
   * @param the_user The user to be added.
   */
  public void addUser(final User the_user)
  {
    my_data_manager.addUser(the_user);
    postLogout();
  }
  
  /**
   * Is the current user an administrator?
   * 
   * @return True if my_current_user is an administrator.
   */
  public boolean isUserAdministrator()
  {
    boolean to_return = false;
    
    if (my_current_user != null && my_current_user.isAdministrator())
    {
      to_return = true;
    }
    
    return to_return;
  }
  
  /**
   * Sets the login view visible.
   */
  private void showLoginPanel()
  {
    my_frame.swapPanel(new GUILoginPanel(this));
  }

  /**
   * Called when a login event has happened. This method
   * will handle all program flow coupled with the login
   * event.
   * 
   * @param the_username The username passed from the gui 
   * as entered into the gui.
   * @param the_password The password for this user.
   */
  public void postLogin(final String the_username,
                        final String the_password)
  {
    System.out.println(the_username + " " + the_password);
    
    //TODO: finish the login function
    if ((my_current_user = my_data_manager.findUser(the_username)) == null)
    {
      my_frame.swapPanel(new GUIRegistrationPanel(this));
    }
    else if (my_data_manager.findUser(the_username).isCorrectPassword(the_password))
    {
      my_frame.swapPanel(new GUIAvailabilityPanel(this)); 
    }
    else
    {
      JOptionPane.showMessageDialog(my_frame, 
                                    "Incorrect or empty password field.", 
                                    "Error in Login",
                                    JOptionPane.ERROR_MESSAGE);
      
    }
  }

  //Posts associated with the File menu.
  /**
   * Called when a open file event happens. This method will open
   * a JFileChooser and allow the user to find a .csv schedule file
   * to open.
   */
  public void postOpen()
  {
    if (my_current_user != null && my_current_user.isAdministrator())
    {
      //TODO: Finish Open... 
    }
    else
    {
      JOptionPane.showMessageDialog(my_frame,  "Must be logged in as an " +
          "administrator to open different schedule files.", "Option Not Available",
          JOptionPane.ERROR_MESSAGE);
    }
  }

  /**
   * Called when a save file event happens. This method will open
   * a JFileChooser and allow the user to specify a directory and
   * a name to save the current schedule object to as a .csv file.
   */
  public void postSave()
  {
    if (my_current_user != null && my_current_user.isAdministrator())
    {
      //TODO: Finish Save... 
    }
    else
    {
      JOptionPane.showMessageDialog(my_frame,  "Must be logged in as an " +
          "administrator to save different schedule files.", "Option Not Available",
          JOptionPane.ERROR_MESSAGE);
    }
  }

  /**
   * Called when a quit program event has happened. This method
   * will handle all program flow coupled with the quit
   * event.
   */
  public void postQuit()
  {
    if (JOptionPane.showConfirmDialog(my_frame, 
                                      "Are you sure you wish to quit?", 
                                      "Goodbye?",
                                      JOptionPane.WARNING_MESSAGE) == 
                                      JOptionPane.OK_OPTION)
    {
      System.exit(0);
    }
  }

  //Posts associated with the Options menu.
  /**
   * Called when someone logs out of the program.
   */
  public void postLogout()
  {
    my_current_user = null;
    my_frame.removeToolBar();
    my_promotion_window.getFrame().dispose();
    showLoginPanel();
  }
  
  /**
   * This method shows the promotion window that is used in order to
   * manage the users administrator status.
   */
  public void showPromotionWindow()
  {
    my_promotion_window = new GUIPromotionWindow(my_data_manager.requestAllUsers(), this);
    my_promotion_window.setVisible(true);
  }
  
  /**
   * This method posts the promotion/demotion of the passed user.
   * 
   * @param the_user The user to promote/demote
   * @param the_choice True if promoting, False if not.
   */
  public void postPromotion(final User the_user, final boolean the_choice)
  {
    if (the_choice)
    {
      the_user.promoteAdmin();
    }
    else
    {
      the_user.demoteAdmin();
    }
  }

  //Posts associated with the View menu.
  /**
   * Handles showing the entire schedule when invoked.
   */
  public void postScheduleEditor()
  {
    if (my_data_manager.isScheduleComplete() && !my_current_user.isAdministrator())
    {
      //TODO: Finish posting the schedule editor.      
    }
    else
    {
      JOptionPane.showMessageDialog(my_frame, "The schedule is incomplete. " +
          "Once complete, you may view the schedule.", 
          "Problem loading view", 
          JOptionPane.ERROR_MESSAGE);
    }

  }

  /**
   * Handles showing the current user's individual schedule when invoked.
   */
  public void postIndividualSchedule()
  {
    if (my_data_manager.isScheduleComplete())
    {
      //TODO: Finish posting the individual schedule for the current user.
    }
    else
    {
      JOptionPane.showMessageDialog(my_frame, "The schedule is incomplete. " +
          "Once complete, you may view your schedule.", 
          "Problem loading view", JOptionPane.ERROR_MESSAGE);
    }
  }

  /**
   * Handles showing the current user's availability as entered.
   */
  public void postAvailabilityEditorStatic()
  {
    if (my_data_manager.isScheduleComplete())
    {
      //TODO: Finish posting the individuals availability.
    }
    else
    {
      JOptionPane.showMessageDialog(my_frame, "The schedule is incomplete. " +
          "Once complete, you may view the availability you entered.", 
          "Problem loading view", JOptionPane.ERROR_MESSAGE);
    }
  }

  //Posts associated with the Help menu.
  /**
   * Handles the About menu action.
   */
  public void postAbout()
  {
    JOptionPane.showMessageDialog(my_frame, 
                                  "This scheduling program was created 2013 by Tristan " +
                                      "Daniel Boucher \nfor the Math Advising and Resource " +
                                      "Center of Tacoma Community College \nto be a solution" +
                                      " to the problem of scheduling tutors for the \ncenter" +
                                      " every quarter", "About the MARC scheduler", 
                                      JOptionPane.INFORMATION_MESSAGE);
  }

  /**
   * Handles the Help menu action.
   */
  public void postHelp()
  {
    //TODO: Finish posting the Help menu.
  }

  /**
   * Posts the submission of the current user's availability.
   * 
   * @param the_availability_cells The matrix of availability cells that
   * comprise this persons availability durring the week.
   * @param the_classes The classes that the user has to check. Contains
   * all classes.
   * @param the_min_max_hours The 2 values for the min and max hours this
   * user is willing to work a week.
   */
  public void postAvailabilityEntry(final AvailabilityCell[][] the_availability_cells,
                                    final Classes[] the_classes,
                                    final int[] the_min_max_hours)
  {
    my_current_user.addAvailability(the_availability_cells, the_classes, the_min_max_hours);
  }

}
